package com.parenting.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.parenting.entities.SystemUserDO;
import com.parenting.enums.ResultEnum;
import com.parenting.exception.BaseException;
import com.parenting.feign.entities.ShopAndUserFeignDTO;
import com.parenting.mapper.SystemUserMapper;
import com.parenting.model.IMPage;
import com.parenting.model.UserLowerDTO;
import com.parenting.properties.BlogProperties;
import com.parenting.properties.ImWechatProperties;
import com.parenting.request.*;
import com.parenting.request.wechat.ForgetPasswordRequest;
import com.parenting.response.AppletShopUserListResponse;
import com.parenting.response.ShopUserResponse;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.parenting.service.SystemUserService;
import com.parenting.tx.QueryResult;
import com.parenting.tx.Tx;
import com.parenting.util.TLSSigAPIv2;
import com.parenting.util.base.Result;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 用户表信息 服务实现类
 * </p>
 *
 * @author 烟台业达-王世玺
 * @since 2021-08-11
 */
@Service
@Slf4j
public class SystemUserServiceImpl extends ServiceImpl<SystemUserMapper, SystemUserDO> implements SystemUserService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    /****
     * 用户注册
     * @param user
     * @return
     */
    @Override
    public Result saveUser(ShopUserAddRequest user,String shopId) {
        //判断手机号和账号是否存在
        LambdaQueryWrapper<SystemUserDO> wrapper=new LambdaQueryWrapper();
        wrapper.eq(SystemUserDO::getAccount,user.getAccount()).or().eq(SystemUserDO::getMobile,user.getMobile());
        Integer integer = baseMapper.selectCount(wrapper);
        //判断该用户是否存在
        if (integer>0){
            throw new BaseException(ResultEnum.ACCOUNT_REPEAT.getCode(),ResultEnum.ACCOUNT_REPEAT.getMessage());
        }
        log.info("=======saveUser============{ }",user);
        SystemUserDO systemUserDO = BeanUtil.copyProperties(user, SystemUserDO.class);
        log.info("=======systemUserDO============{ }",systemUserDO);
        systemUserDO.setShopId(shopId);
        String password = passwordEncoder.encode(user.getPassword());

        log.info("=======password============{ }",password);
        systemUserDO.setPassword(password);
        baseMapper.insert(systemUserDO);
        return Result.buildSuccess();
    }


    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Transactional
    @Override
    public Result registerUser(AppletRegisterUser user) {
        //判断手机号和账号是否存在
        LambdaQueryWrapper<SystemUserDO> wrapper=new LambdaQueryWrapper();
        wrapper.eq(SystemUserDO::getAccount,user.getAccount()).or().eq(SystemUserDO::getMobile,user.getMobile());
        Integer integer = baseMapper.selectCount(wrapper);
        //判断该用户是否存在
        if (integer>0){
            throw new BaseException(ResultEnum.ACCOUNT_REPEAT.getCode(),"账号或手机号已存在！");
        }
        String s = stringRedisTemplate.opsForValue().get("user:phone:" + user.getMobile());
        log.info("user==== { }" + user);

        log.info("s====  { }" + s);
        if (null==s){
             return Result.buildError("验证码过期！");
        }else if(!user.getCode().equals(s)){
            return Result.buildError("手机验证码不正确！");
        }

        SystemUserDO systemUserDO = BeanUtil.copyProperties(user, SystemUserDO.class);
        String password = passwordEncoder.encode(user.getPassword());
        systemUserDO.setPassword(password);
        baseMapper.insert(systemUserDO);
        //授权  指定权限
        List<String> ids=new ArrayList<>();
        ids.add("73");
        ids.add("88");
        ids.add("1");
        ids.add("2");
        ids.add("3");
        this.saveUserAndResources(systemUserDO.getId(),ids);
        return Result.buildSuccess();
    }

    @Override
    public void updateUser(ShopUserUpdateRequest user) {
        SystemUserDO systemUserDO = BeanUtil.copyProperties(user, SystemUserDO.class);
        systemUserDO.setUpdateDate(new Date());
        baseMapper.updateById(systemUserDO);
    }

    @Override
    public IPage<ShopUserResponse> findUserLisByShopId(ShopUserPageListRequest userREQ) {


        IPage<ShopUserResponse> userLisByShopId = baseMapper.findUserLisByShopId(userREQ.getPage(), userREQ.getShopId());
        return userLisByShopId;
    }

    @Override
    public void saveUserAndResources(String userId, List<String> resourcesIds) {
        log.info("saveUserAndResources=========== {}",resourcesIds);
        if (null==resourcesIds || resourcesIds.size()<=0){
            throw new BaseException(ResultEnum.ACCOUNT_JURISDICTION.getCode(),ResultEnum.ACCOUNT_JURISDICTION.getMessage());
        }else{
            log.info("baseMapper.deleteUserAndResources(userId);=========== {}","被执行");
            baseMapper.deleteUserAndResources(userId);
            baseMapper.saveUserAndResources(userId,resourcesIds);
        }
    }

    @Override
    public void deleteUser(String userId) {
        SystemUserDO  userDO=new SystemUserDO();
        userDO.setId(userId);
        userDO.setUpdateDate(new Date());
        userDO.setIsEnabled(2);
        baseMapper.updateById(userDO);
    }

    @Override
    public SystemUserDO findUserByUserName(String username) {
        LambdaQueryWrapper<SystemUserDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SystemUserDO::getAccount,username);
        wrapper.eq(SystemUserDO::getIsAccountNonExpired,1);
        wrapper.eq(SystemUserDO::getIsAccountNonLocked,1);
        wrapper.eq(SystemUserDO::getIsCredentialsNonExpired,1);
        wrapper.eq(SystemUserDO::getIsEnabled,1);
        return baseMapper.selectOne(wrapper);
    }

    @Override
    public SystemUserDO findUserByUserMobile(String mobile) {
        LambdaQueryWrapper<SystemUserDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SystemUserDO::getMobile,mobile);
        wrapper.eq(SystemUserDO::getIsAccountNonExpired,1);
        wrapper.eq(SystemUserDO::getIsAccountNonLocked,1);
        wrapper.eq(SystemUserDO::getIsCredentialsNonExpired,1);
        wrapper.eq(SystemUserDO::getIsEnabled,1);
        return baseMapper.selectOne(wrapper);
    }

    @Override
    public SystemUserDO findUserByUserWXOpenId(String wxOpenId) {
        LambdaQueryWrapper<SystemUserDO> wrapper =new LambdaQueryWrapper<SystemUserDO> ();
        wrapper.eq(SystemUserDO::getWxOpenId,wxOpenId);
        wrapper.eq(SystemUserDO::getIsAccountNonExpired,1);
        wrapper.eq(SystemUserDO::getIsAccountNonLocked,1);
        wrapper.eq(SystemUserDO::getIsCredentialsNonExpired,1);
        wrapper.eq(SystemUserDO::getIsEnabled,1);
        return baseMapper.selectOne(wrapper);
    }



    @Override
    public Result updatePassword(UserUpdatePasswordRequest req) {
        if(StringUtils.isEmpty(req.getUserId())) {
            return Result.buildError("用户ID不能为空，请重试");
        }
        if(StringUtils.isEmpty(req.getNewPassword())) {
            return Result.buildError("新密码不能为空，请重试");
        }
        if(StringUtils.isEmpty(req.getRepPassword())) {
            return Result.buildError("确认密码不能为空，请重试");
        }
        if( !req.getNewPassword().equals( req.getRepPassword() )) {
            return Result.buildError("新密码与确认密码不一致，请重试");
        }
       SystemUserDO sysUser = baseMapper.selectById(req.getUserId());
        if(sysUser == null) {
            return Result.buildError("用户不存在，请重试");
        }
        // 如果有原密码，则校验是否正确
        if(StringUtils.isNotEmpty(req.getOldPassword())) {
            if( !passwordEncoder.matches( req.getOldPassword(), sysUser.getPassword() ) ) {
                return Result.buildError("原密码输入错误");
            }
        }
        // 校验都通过，将新密码进行加密存储
        sysUser.setPassword( passwordEncoder.encode(req.getNewPassword()) );
        sysUser.setPwdUpdateDate(new Date());
        baseMapper.updateById(sysUser);
        return Result.buildSuccess("密码修改成功！");
    }

    @Override
    public Result updateLoginUserPassword(UpdateLoginUserPasswordRequest req, String loginUserId) {
        if(StringUtils.isEmpty(req.getNewPassword())) {
            return Result.buildError("新密码不能为空，请重试");
        }
        if(StringUtils.isEmpty(req.getRepPassword())) {
            return Result.buildError("确认密码不能为空，请重试");
        }
        log.info("============req.getNewPassword().equals( req.getRepPassword() )=========== {}",!req.getNewPassword().equals( req.getRepPassword() ));

        log.info("============req.getNewPassword()=========== {}",req.getNewPassword());
        log.info("============req.getRepPassword() =========== {}",req.getRepPassword() );
        if( !req.getNewPassword().equals( req.getRepPassword() )) {
            return Result.buildError("新密码与确认密码不一致，请重试");
        }
        SystemUserDO sysUser = baseMapper.selectById(loginUserId);
        if(sysUser == null) {
            return Result.buildError("用户不存在，请重试");
        }
        // 校验都通过，将新密码进行加密存储
        sysUser.setPassword( passwordEncoder.encode(req.getNewPassword()) );
        sysUser.setPwdUpdateDate(new Date());
        baseMapper.updateById(sysUser);
        return Result.buildSuccess("密码修改成功！");
    }

    @Override
    public Result updateExtractPassword(UpdateExtractPasswordRequest extractPasswordRequest, String userId) {
        if (!extractPasswordRequest.getNewExtractPassword().equals(extractPasswordRequest.getRepExtractPassword())){
            return  Result.buildError("新密码与确认密码不一致，请重试");
        }
        SystemUserDO sysUser = baseMapper.selectById(userId);
        if(sysUser == null) {
            return Result.buildError("用户不存在，请重试");
        }
        String  password=passwordEncoder.encode(extractPasswordRequest.getExtractOldPassword());
        log.info("password=============== {} ", password);
        log.info("extractPasswordRequest.getExtractOldPassword()=============== {} ", extractPasswordRequest.getExtractOldPassword());
        log.info("sysUser.getExtractPassword()=============== {} ", sysUser.getExtractPassword());
        // 如果有原密码，则校验是否正确
        if(StringUtils.isNotEmpty(extractPasswordRequest.getExtractOldPassword())) {
            if(!passwordEncoder.matches(extractPasswordRequest.getExtractOldPassword(), sysUser.getExtractPassword()) ) {
                return Result.buildError("原密码输入错误!");
            }
        }
       //校验都通过，将新密码进行加密存储
        sysUser.setExtractPassword( passwordEncoder.encode(extractPasswordRequest.getNewExtractPassword()) );
        sysUser.setPwdUpdateDate(new Date());
        baseMapper.updateById(sysUser);
        return Result.buildSuccess();
    }

    @Override
    public Result saveExtractPassword(AddExtractPasswordRequest extractPasswordRequest, String userId) {
        if (!extractPasswordRequest.getNewExtractPassword().equals(extractPasswordRequest.getRepExtractPassword())){
            return  Result.buildError("新密码与确认密码不一致，请重试");
        }
        SystemUserDO sysUser = baseMapper.selectById(userId);
        if(sysUser == null) {
            return Result.buildError("用户不存在，请重试");
        }
        log.info("saveExtractPassword==================== {} ",passwordEncoder.encode(extractPasswordRequest.getNewExtractPassword()));
        sysUser.setExtractPassword(passwordEncoder.encode(extractPasswordRequest.getNewExtractPassword()) );
        sysUser.setPwdUpdateDate(new Date());
        baseMapper.updateById(sysUser);
        return Result.buildSuccess();
    }

    @Override
    public void ShopAndUser(ShopAndUserFeignDTO shopAndUserFeignDTO) {
        SystemUserDO userDO = baseMapper.selectById(shopAndUserFeignDTO.getUserId());
        userDO.setShopId(shopAndUserFeignDTO.getShopId());
        userDO.setRoleName("店长");
        userDO.setUpdateDate(new Date());
        baseMapper.updateById(userDO);

    }

    @Autowired
    private BlogProperties blogProperties;
    @Override
    public IMPage<AppletShopUserListResponse> getShopUserList(String ShopId, AppletShopUserListRequest request) {

        log.info("request.getCurrent()====================== {}", request.getCurrent());
        log.info("request.getSize()====================== {}", request.getSize());
        LambdaQueryWrapper<SystemUserDO> wrapper =new LambdaQueryWrapper<>();
        wrapper.eq(SystemUserDO::getShopId,ShopId);
        if (StringUtils.isNotBlank(request.getSearch())){
            wrapper.like(SystemUserDO::getFullName,request.getSearch()).or().like(SystemUserDO::getJobNumber,request.getSearch());
        }
        //根据店铺ID查询 店铺人员分页列表
        IPage<SystemUserDO> systemUserDOIPage = baseMapper.selectPage(request.getPage(), wrapper);
        //获得 IM 配置
        ImWechatProperties wechatIm = blogProperties.getWechatIm();
        System.out.println(wechatIm.toString());
        //实例化 IM 通讯类  获得 IM通讯 用于查询该店铺下 那些人员 在线
        TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(wechatIm.getSdkAppId(), wechatIm.getKey());
        //进行签名
        String s = tlsSigAPIv2.genUserSig("administrator", wechatIm.getExpire());
        //封装请求数据
//        TXOnline txOnline = new TXOnline();
//        txOnline.setTo_Account(getUserId(systemUserDOIPage.getRecords()));
//        txOnline.setIsNeedDetail(0);
        Map<String ,Object> map=new HashMap();
        map.put("To_Account",getUserId(systemUserDOIPage.getRecords()));
        map.put("IsNeedDetail",0);
        //请求IM 是否在线
        JSONObject jsonObject = tlsSigAPIv2.requestPost(JSONObject.fromObject(map), s);
        log.info("jsonObject.getString(\"ActionStatus\")====> {}",jsonObject.getString("ActionStatus"));

        if(null!=jsonObject){
            Tx feeEntity = com.alibaba.fastjson.JSONObject.parseObject(jsonObject.toString(),Tx.class);
            log.info("feeEntity====> {}",feeEntity);
//            Tx a = createFeeEntity(Tx.class, jsonObject.toString());
//            log.info(" Tx a====> {}",a);
            if (null!=feeEntity.getActionStatus()){
                List<AppletShopUserListResponse> appletShopUserListResponse = getAppletShopUserListResponse(systemUserDOIPage.getRecords(), feeEntity.getQueryResult());
                IMPage<AppletShopUserListResponse> page=new IMPage<>();
                page.setRecords(appletShopUserListResponse);
                page.setCurrent(systemUserDOIPage.getCurrent());
                page.setSize(systemUserDOIPage.getSize());
                page.setTotal(systemUserDOIPage.getTotal());
                return page;
            }
        }else{
            IMPage<AppletShopUserListResponse> page=new IMPage<>();
            List<AppletShopUserListResponse>  appletShopUserListResponse=new ArrayList<>();
            for (SystemUserDO su: systemUserDOIPage.getRecords()) {
                appletShopUserListResponse.add(BeanUtil.copyProperties(su,AppletShopUserListResponse.class));
            }
            page.setRecords(appletShopUserListResponse);
            page.setCurrent(systemUserDOIPage.getCurrent());
            page.setSize(systemUserDOIPage.getSize());
            page.setTotal(systemUserDOIPage.getTotal());
            return page;
        }
        return null;
    }



    @Override
    public Result forgetPassword(ForgetPasswordRequest forgetPasswordRequest) {
        SystemUserDO userDO=new SystemUserDO();
        userDO.setMobile(forgetPasswordRequest.getPhone());
        userDO.setAccount(forgetPasswordRequest.getAccount());
        userDO.setPassword( passwordEncoder.encode(forgetPasswordRequest.getPassword()));
        baseMapper.update(userDO,new LambdaUpdateWrapper<SystemUserDO>().eq(SystemUserDO::getAccount,userDO.getAccount()));
        return Result.buildSuccess();
    }

    @Override
    public List<UserLowerDTO> getUserLowerDtoByShopId(String shopId) {
        List<UserLowerDTO> list=new ArrayList<>();
        List<SystemUserDO> systemUserDOS = baseMapper.selectList(new LambdaQueryWrapper<SystemUserDO>().eq(SystemUserDO::getShopId, shopId));
        if (null!=systemUserDOS&&systemUserDOS.size()>0){
            for (SystemUserDO s:systemUserDOS) {
                UserLowerDTO userLowerDTO = BeanUtil.copyProperties(s, UserLowerDTO.class);
                list.add(userLowerDTO);
            }
        }
        return list;
    }

    /***
     * 用户转换JSON 把JSON转换成对象
     * @param tClass
     * @param feeJSON
     * @param <T>
     * @return
     */
    private  <T> T createFeeEntity(Class<T> tClass, String feeJSON) {
        if (StringUtils.isNotBlank(feeJSON)) {
            ObjectMapper mapper = new ObjectMapper();
            try {
                T t = mapper.readValue(feeJSON,tClass);
                return t;
            } catch (IOException e) {
                log.info(e.getMessage(), e);
                return null;
            }
        } else {
            return null;
        }
    }

    /***
     * 获得当前店铺店员的所有ID 用于去IM查询是否在线
     * @param systemUserDOS
     * @return
     */
    private List<String> getUserId(List<SystemUserDO> systemUserDOS){
        if (null!=systemUserDOS&&systemUserDOS.size()>0){
            List<String> list=new ArrayList<>();
            for (SystemUserDO s:systemUserDOS) {
                list.add(s.getAccount());
            }
            return list;
        }
        return null;
    }

    /***
     * @param userDOS 查出的店铺用户
     * @param results  IM返回的在线用户
     * @return   List<AppletShopUserListResponse> 重新封装成一个对象
     */
    private List<AppletShopUserListResponse> getAppletShopUserListResponse(List<SystemUserDO> userDOS,List<QueryResult> results){
        List<AppletShopUserListResponse>  listResponses=new ArrayList<>();
        for (SystemUserDO s:userDOS){
            AppletShopUserListResponse appletShopUserListResponse= BeanUtil.copyProperties(s, AppletShopUserListResponse.class);
            if (null!=results&&results.size()>0){
                for (QueryResult q:results){
                    if (appletShopUserListResponse.getAccount().equals(q.getTo_Account())){
                        appletShopUserListResponse.setOnline(q.getStatus());
                    }
                }
            }
            listResponses.add(appletShopUserListResponse);
        }
        return listResponses;
    }

}
